#pragma once
#ifndef LIT_STANDALONE
#ifndef __MEMORY__WATCHER__INCLUDED__H__
#define __MEMORY__WATCHER__INCLUDED__H__

#include <string>
#include <vector>
#include <LitString.h>
#include <OgreLogManager.h>
#include <OgreStringConverter.h>

namespace Lit
{
	class MemoryWatcher
	{
	public:
		typedef unsigned long		address_t;
		struct block_t
		{
			block_t( const address_t addr = address_t(0), const String &file = String(), const int line = 0 )
				: Address( addr )
				, File( file )
				, Line( line ){}
			block_t( const block_t & rk ){ Address = rk.Address; File = rk.File; Line = rk.Line; }
			~block_t( ){}

			address_t			Address;
			String			File;
			int					Line;
		};
		typedef std::vector<block_t>	block_list_t;
		
	protected:
		block_list_t					mBlocks;
		Ogre::Log*						mLog;
	public:
		MemoryWatcher( const String &logname = "memory_watcher.log" )
		{
			mLog = Ogre::LogManager::getSingleton().createLog(logname);
		}
		~MemoryWatcher( )
		{
			Ogre::LogManager::getSingleton().destroyLog(mLog);
		}

		bool hasAllocation( const address_t addr ) const
		{
			for( auto i=mBlocks.begin(); i!=mBlocks.end(); i++ ){
				if( i->Address == addr ) return true;
			}
			return false;
		}
		void recordAllocation( const address_t addr, const String &file, const int line )
		{
			String saddr(Ogre::StringConverter::toString(addr));
			if( hasAllocation( addr ) )
				mLog->logMessage( "Already allocated "+saddr );
			mBlocks.push_back( block_t( addr, file, line ) );
		}

		void dumpAllocations( )
		{
			mLog->logMessage("Allocation List:");
			for( auto i=mBlocks.begin(); i!=mBlocks.end(); i++ ){
				String saddr = Ogre::StringConverter::toString(i->Address);
				String sln = Ogre::StringConverter::toString(i->Line);
				mLog->logMessage("\t+ "+saddr+"| "+i->File+" ("+sln+")");
			}
		}
	};
};

#endif


#endif